#include "../include/LRUCache.h"
#include <iostream>
using Itera =
    std::list<std::pair<std::string, std::vector<std::string>>>::iterator;

using listElement = std::pair<std::string, std::vector<std::string>>;

using namespace std;

int LRUCache::get(std::string query,
                  std::pair<std::string, std::vector<std::string>>& res) {
    if (!_cache.count(query)) {
        return -1;
    } else {
        Itera it = _cache[query];
        listElement tmp = *it;  // 保存队列元素的值
        //std::cout << (*it).first << std::endl;

        res = *it;  // 返回队列元素的值

        _dlist.erase(it);  // 删除队列元素

        _dlist.push_front(tmp);  // 把元素插入队列头

        it = _dlist.begin();
        _cache[query] = it;

        if (_pendingHash.count(query)) {
            Itera pendingit = _pendingHash[query];
            _pendingUpdateList.erase(pendingit);

            _pendingUpdateList.push_front(tmp);

            pendingit = _pendingUpdateList.begin();
            _pendingHash[query] = pendingit;
        } else {
            _pendingUpdateList.push_front(tmp);

            Itera it = _pendingUpdateList.begin();

            _pendingHash[query] = it;

            if (_pendingUpdateList.size() > _pendingcapacity) {
                listElement tmp = _pendingUpdateList.back();

                _pendingHash.erase(tmp.first);

                _pendingUpdateList.pop_back();
            }
        }
        return 0;
    }
}

int LRUCache::put(std::string query, std::vector<std::string> recommand) {
    if (_cache.count(query)) {
        // 已存在，要修改
        // 删掉队列中的旧的
        Itera it = _cache[query];
        _dlist.erase(it);

        // 放新的进队列
        _dlist.push_front(std::make_pair(query, recommand));

        // 更新hash
        it = _dlist.begin();
        _cache[query] = it;

        if (_pendingHash.count(query)) {
            Itera pendingit = _pendingHash[query];
            _pendingUpdateList.erase(pendingit);

            _pendingUpdateList.push_front(std::make_pair(query, recommand));

            pendingit = _pendingUpdateList.begin();
            _pendingHash[query] = pendingit;
        } else {
            _pendingUpdateList.push_front(std::make_pair(query, recommand));

            Itera it = _pendingUpdateList.begin();

            _pendingHash[query] = it;

            if (_pendingUpdateList.size() > _pendingcapacity) {
                listElement tmp = _pendingUpdateList.back();

                _pendingHash.erase(tmp.first);

                _pendingUpdateList.pop_back();
            }
        }

    } else {
        // 不存在，要插入
        _dlist.push_front(std::make_pair(query, recommand));

        Itera it = _dlist.begin();

        _pendingUpdateList.push_front(std::make_pair(query, recommand));

        Itera pendingit = _pendingUpdateList.begin();

        _pendingHash[query] = pendingit;

        _cache[query] = it;
        if (_pendingUpdateList.size() > _pendingcapacity) {
            listElement tmp = _pendingUpdateList.back();

            _pendingHash.erase(tmp.first);

            _pendingUpdateList.pop_back();
        }
        if (_dlist.size() > _capacity) {
            listElement tmp = _dlist.back();

            _cache.erase(tmp.first);

            _dlist.pop_back();
        }
    }
    return 0;
}

int LRUCache::readToFile() {
    // 创建一个名为 "example.txt" 的输入文件流（ifstream）对象
    std::ifstream LruIn("./LruOut.dat");

    // 检查文件是否成功打开
    if (!LruIn) {
        std::cerr << "Error: Cannot open the file." << std::endl;
        return 1;
    }

    std::string line;

    // 使用 getline 函数逐行读取文件内容
    while (getline(LruIn, line)) {
        // 使用istringstream将字符串视为输入流
        std::istringstream line_stream(line);
        string word;
        line_stream >> word;
        string wordtemp = word; //用户输入的关键词
        vector<string> keytemp; // 服务端推荐的相似关键词
        // 使用 >> 运算符从字符串流中逐词读取
        while (line_stream >> word) {
            //cout << "Word: " << word << endl;
            keytemp.push_back(word);
        }
        pair<string, vector<string>> pairtemp = {wordtemp, keytemp};
        _dlist.push_back(pairtemp);
        //_cache.insert(make_pair(wordtemp,_dlist.back()));
        _cache[wordtemp] = --_dlist.end();  
    }
    // 关闭文件
    LruIn.close();

    return 0;
}

int LRUCache::writeToFile() {
    std::ofstream LruOut("./LruOut.dat");
    if (!LruOut.good()) {
        std::cerr << "fstream is corrupted!" << endl;
        return -1;
    }
    for (auto pairtemp : _dlist) {
        auto vectemp = pairtemp.second;
        LruOut << pairtemp.first << " ";
        for (auto strtemp : vectemp) {
            LruOut << strtemp << " ";
        }
        LruOut << endl;
    }
    LruOut.close();
    return 0;
}

int LRUCache::clearpending(){
    _pendingHash.clear();
    _pendingUpdateList.clear();
    return 0;
}